package com.gitee.wsl.struct.grammar.ast.process.marker.block


import com.gitee.wsl.struct.grammar.ast.node.NodeType
import com.gitee.wsl.struct.grammar.ast.process.constraints.TextReadConstraints
import com.gitee.wsl.struct.grammar.ast.process.marker.ProductionHolder
import com.gitee.wsl.text.reader.line.LookaheadText


interface MarkerBlock {

    fun getNextInterestingOffset(pos: LookaheadText.Position): Int

    fun isInterestingOffset(pos: LookaheadText.Position): Boolean

    fun allowsSubBlocks(): Boolean

    fun processToken(pos: LookaheadText.Position,
                     currentConstraints: TextReadConstraints
    ): ProcessingResult

    fun getBlockConstraints(): TextReadConstraints

    /**
     * @param action to accept
     * @return true if this block is to be deleted after this action, false otherwise
     */
    fun acceptAction(action: ClosingAction): Boolean

    enum class ClosingAction {
        DONE {
            override fun doAction(marker: ProductionHolder.Marker, type: NodeType) {
                marker.done(type)
            }
        },
        DROP {
            override fun doAction(marker: ProductionHolder.Marker, type: NodeType) {
            }
        },
        DEFAULT {
            override fun doAction(marker: ProductionHolder.Marker, type: NodeType) {
                throw UnsupportedOperationException("Should not be invoked")
            }
        },
        NOTHING {
            override fun doAction(marker: ProductionHolder.Marker, type: NodeType) {
            }
        };

        abstract fun doAction(marker: ProductionHolder.Marker, `type`: NodeType)
    }

    enum class EventAction {
        PROPAGATE,
        CANCEL
    }

    class ProcessingResult internal constructor(val childrenAction: ClosingAction,
                                                val selfAction: ClosingAction,
                                                val eventAction: EventAction
    ) {

        companion object {
            val PASS: ProcessingResult = ProcessingResult(ClosingAction.NOTHING, ClosingAction.NOTHING, EventAction.PROPAGATE)
            val CANCEL: ProcessingResult = ProcessingResult(ClosingAction.NOTHING, ClosingAction.NOTHING, EventAction.CANCEL)
            val DEFAULT: ProcessingResult = ProcessingResult(ClosingAction.DEFAULT, ClosingAction.DONE, EventAction.PROPAGATE)
        }

    }
}
